#!/bin/env perl

#
# Modules.
#

use lib qw( lib root/SOCK/lib );

use Modern::Perl;

use Getopt::Long;
use IPC::Run3;
use iSOCK;
use iSOCK::Model::App;
use SOCK::LOG;
use SOCK::SVN::Product;
use Try::Tiny;

#
# Options.
#

my $tool = 'isock_add_specification';

my %option;
GetOptions ( \%option, qw{
  owner=s
  id=s
  product=s
  force
  repository_url=s
  repository_login=s
  repository_password=s
} ) and ( $option{id} && $option{owner} ) or die "Usage: $tool --id FOO --owner jdoe [--product BAR-A]";

die "Wrong '$option{product}' product ID!" if $option{product} && $option{product} !~ /^ [A-Z][A-Z0-9]+ - [A-Z] $/x;

#
# Hi.
#

my $log = SOCK::LOG->new ({ file => "$tool.log" });

$log->say_n_right ( "Tool '$tool' started..." );

#
# Core.
#

my $schema = iSOCK::Model::App->new;

for my $id ( $option{id} ) {
  {
    $log->say_n_right ( "Adding to subversion..." );

    spawn ( "svn checkout --depth empty "
    . ( $option{repository_url} || SOCK::SVN::Product->_repository_url )
    . ( $option{repository_login}    ? " --repository_login " .    $option{repository_login}    : "" )
    . ( $option{repository_password} ? " --repository_password " . $option{repository_password} : "" )
    . " ."
    );

    spawn ( "svn update --depth empty $id" );

    if ( -d $id ) {
      $log->counsel ( "Specification already exists in subversion repository." );
    }
    else {
      mkdir  $id,                    oct 755;
      mkdir "$id/$_",                oct 755 for qw( branches tags trunk );
      mkdir "$id/trunk/$_",          oct 755 for qw( specification followup snippets integration );
      mkdir "$id/trunk/snippets/$_", oct 755 for qw( include source );

      spawn ( "svn add --depth infinity $id" );

      spawn ( "svn commit --message 'creation' $id" );
    }

    $log->left_n_say ( "Done." );
  }
  
  {
    $log->say_n_right ( "Adding to database..." );
    
    my $specification_r = $schema->resultset ( 'Specification' )->find ( $id );

    if ( $specification_r ) {
      $log->say ( "Specification already exists in iSOCK database." );
    }
    else {
      $specification_r = $schema->resultset ( 'Specification' )->create ({ id => $id }); # FIXME repository_id == 'secure' as an option?
    }

    if ( my $user_r = $schema->resultset ( 'User' )->find ( $option{owner} ) ) {
      $schema->resultset ( 'UserToSpecification' )->update_or_create ({ user_id => $user_r->id, specification_id => $specification_r->id, authorization_id => $_ }) for qw( owner writer follower );

      if ( my $product = $option{product} ) {
        if ( my $product_r = $schema->resultset ( 'Product' )->find ( $product ) ) {
          $product_r->update ({ specification_id => $specification_r->id });
        }
        else {
          $schema->resultset ( 'Product' )->create ({ id => $product, specification_id => $specification_r->id });
        }

        $schema->resultset ( 'UserToProduct' )->update_or_create ({ user_id => $user_r->id, product_id => $product, authorization_id => 'owner' });
      }
    }
    else {
      $log->counsel ( "Could not find any '$option{owner}' user in iSOCK database." );
    }

    $log->left_n_say ( "Done." );
  }
}

#
# Bye.
#

$log->left_n_say ( "Tool '$tool' done." );

#
# Subs.
#

sub spawn {
  my ( $command ) = @_;
  
  ( my $said_command = $command ) =~ s/ ( \s+ --(file_)?indent \s+ \d+ | \s+ --repository_password \s+ '[^']+' ) //gx;
  
  my ( $stdout, $stderr );

  $log->say_n_right ( "Spawning \"$said_command\" command..." );
  try {
    run3 ( $command, undef, \$stdout, \$stderr );
    $log->left_n_say ( "Done." );
  }
  catch {
    $log->left_n_say ( "Failed!" );
  };

  return $?;
}
